using System;
using System.Text;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.SavedGame;
using UnityEngine;

namespace BCW
{
	internal sealed class GooglePullHelper
	{
		private const string SavedGameClientIsNullMessage = "[Rilisoft] SavedGame client is null.";

		private bool _invoked;

		private DataSource _currentDataSource = DataSource.ReadNetworkOnly;

		private string _accumulatedMerge;

		private readonly string _filename;

		private readonly Func<string, string, string> _merger;

		private readonly Action<string> _readComplete;

		private string Filename
		{
			get
			{
				return _filename;
			}
		}

		private static ISavedGameClient SavedGame
		{
			get
			{
				try
				{
					return GpgWrapper.instance.SavedGame;
				}
				catch (NullReferenceException)
				{
					return null;
				}
			}
		}

		internal GooglePullHelper(string filename, Func<string, string, string> merger, Action<string> readComplete)
		{
			if (merger == null)
			{
				throw new ArgumentNullException("merger");
			}
			_filename = filename ?? string.Empty;
			_merger = merger;
			_readComplete = readComplete;
		}

		internal void Run()
		{
			bool flag = GpgWrapper.instance.IsAuthenticated();
			if (!_invoked)
			{
				_invoked = true;
				if (flag)
				{
					RunAuthenticated();
				}
				else
				{
					GpgWrapper.instance.TryAuthenticate(HandleAuthenticated);
				}
			}
		}

		internal static string GetDescription(ISavedGameMetadata metadata)
		{
			if (metadata == null)
			{
				return string.Empty;
			}
			return metadata.Description ?? string.Empty;
		}

		private static string ShortenSubstring(string s, int length)
		{
			if (string.IsNullOrEmpty(s))
			{
				return string.Empty;
			}
			if (length <= 0)
			{
				return string.Empty;
			}
			if (length >= s.Length)
			{
				return s;
			}
			return s.Substring(0, length) + "...";
		}

		private void RunAuthenticated()
		{
			if (SavedGame == null)
			{
				if (_readComplete != null)
				{
					_readComplete("Exception");
				}
				BCWDebug.LogError("SavedGame == null", "GPG");
			}
			else
			{
				SavedGame.OpenWithManualConflictResolution(Filename, _currentDataSource, true, HandleOpenConflict, HandleOpenCompleted);
			}
		}

		private void HandleAuthenticated(bool authenticated)
		{
			try
			{
				if (!authenticated)
				{
					if (_readComplete != null)
					{
						_readComplete("Authenticate error");
					}
					BCWDebug.LogError("Authentication callback failed", "GPG");
				}
				else if (!GpgWrapper.instance.IsAuthenticated())
				{
					if (_readComplete != null)
					{
						_readComplete("Authenticate error");
					}
					BCWDebug.LogError("Authentication callback succeeded, but user still not authenticated", "GPG");
				}
				else
				{
					RunAuthenticated();
				}
			}
			catch (Exception ex)
			{
				if (_readComplete != null)
				{
					_readComplete("Authenticate error");
				}
				BCWDebug.Log(string.Format("Request failed with `{0}`: {1}", ex.GetType(), ex.Message), "GPG", LogType.Exception);
			}
		}

		private void HandleOpenConflict(IConflictResolver resolver, ISavedGameMetadata original, byte[] originalData, ISavedGameMetadata unmerged, byte[] unmergedData)
		{
			try
			{
				if (originalData == null)
				{
					resolver.ChooseMetadata(unmerged);
					return;
				}
				if (unmergedData == null)
				{
					resolver.ChooseMetadata(original);
					return;
				}
				string text = Encoding.UTF8.GetString(originalData, 0, originalData.Length) ?? string.Empty;
				string text2 = Encoding.UTF8.GetString(unmergedData, 0, unmergedData.Length) ?? string.Empty;
				string text3 = _merger(text, text2);
				if (object.ReferenceEquals(text3, text))
				{
					resolver.ChooseMetadata(original);
					return;
				}
				if (object.ReferenceEquals(text3, text2))
				{
					resolver.ChooseMetadata(unmerged);
					return;
				}
				if (_accumulatedMerge == null)
				{
					_accumulatedMerge = text3;
				}
				else
				{
					_accumulatedMerge = _merger(_accumulatedMerge, text3);
				}
				ISavedGameMetadata savedGameMetadata;
				if (original.LastModifiedTimestamp >= unmerged.LastModifiedTimestamp)
				{
					savedGameMetadata = original;
				}
				else
				{
					savedGameMetadata = unmerged;
				}
				ISavedGameMetadata chosenMetadata = savedGameMetadata;
				resolver.ChooseMetadata(chosenMetadata);
			}
			catch (Exception ex)
			{
				if (_readComplete != null)
				{
					_readComplete("Request failed");
				}
				BCWDebug.Log(string.Format("Request failed with `{0}`: {1}", ex.GetType(), ex.Message), "GPG", LogType.Exception);
			}
		}

		private void HandleOpenCompleted(SavedGameRequestStatus requestStatus, ISavedGameMetadata metadata)
		{
			try
			{
				switch (requestStatus)
				{
				case SavedGameRequestStatus.Success:
					SavedGame.ReadBinaryData(metadata, HandleReadCompleted);
					break;
				case SavedGameRequestStatus.TimeoutError:
					if (_currentDataSource == DataSource.ReadCacheOrNetwork)
					{
						if (_readComplete != null)
						{
							_readComplete("Exception: " + requestStatus);
						}
						BCWDebug.Log("Exception: " + requestStatus, "GPG", LogType.Exception);
					}
					else
					{
						_currentDataSource = DataSource.ReadCacheOrNetwork;
						SavedGame.OpenWithManualConflictResolution(Filename, _currentDataSource, true, HandleOpenConflict, HandleOpenCompleted);
					}
					break;
				case SavedGameRequestStatus.AuthenticationError:
					GpgWrapper.instance.TryAuthenticate(HandleAuthenticated);
					break;
				default:
					if (_readComplete != null)
					{
						_readComplete("Exception: " + requestStatus);
					}
					BCWDebug.Log("Exception: " + requestStatus, "GPG", LogType.Exception);
					break;
				}
			}
			catch (Exception ex)
			{
				if (_readComplete != null)
				{
					_readComplete("Exception: " + requestStatus);
				}
				BCWDebug.Log(string.Format("Request failed with `{0}`: {1}", ex.GetType(), ex.Message), "GPG", LogType.Exception);
			}
		}

		private void HandleReadCompleted(SavedGameRequestStatus requestStatus, byte[] data)
		{
			try
			{
				switch (requestStatus)
				{
				case SavedGameRequestStatus.Success:
				{
					string text = ((data == null) ? string.Empty : Encoding.UTF8.GetString(data, 0, data.Length));
					BCWDebug.Log(string.Format("unmergedResult: {0}", text), "GPG");
					string text2 = ((_accumulatedMerge == null) ? text : _merger(_accumulatedMerge, text));
					if (_readComplete != null)
					{
						_readComplete(text2);
					}
					BCWDebug.Log(string.Format("result:         {0}", text2), "GPG");
					break;
				}
				case SavedGameRequestStatus.AuthenticationError:
					GpgWrapper.instance.TryAuthenticate(HandleAuthenticated);
					break;
				default:
					if (_readComplete != null)
					{
						_readComplete("Exception: " + requestStatus);
					}
					BCWDebug.Log("Exception: " + requestStatus, "GPG", LogType.Exception);
					break;
				}
			}
			catch (Exception ex)
			{
				if (_readComplete != null)
				{
					_readComplete("Request failed");
				}
				BCWDebug.Log(string.Format("Request failed with `{0}`: {1}", ex.GetType(), ex.Message), "GPG", LogType.Exception);
			}
		}
	}
}
